/**
 * 一、promise:
 *    1、概念：`Promise`对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
            一个 Promise 必然处于以下几种状态之一：
                - 待定（pending）: 初始状态，既没有被兑现，也没有被拒绝。
                - 已兑现（fulfilled）: 意味着操作成功完成。
                - 已拒绝（rejected）: 意味着操作失败。
                promise:状态变化不可逆
 *    2、作用：
      3、方法
            Promise.all(iterable)         //所有的都成功
                方法接收一个promise的iterable类型（注：Array，Map，Set都属于ES6的iterable类型）的输入，
                并且只返回一个Promise实例，那个输入的所有promise的resolve回调的结果是一个数组。
            Promise.allSettled(iterable)
                (1)该Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise，
                   并带有一个对象数组，每个对象表示对应的promise结果。
                (2)当您有多个彼此不依赖的异步任务成功完成时，或者您总是想知道每个promise的结果时，通常使用它。
                (3)相比之下，Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束。
            Promise.any(iterable)         //只有一个成功
            Promise.prototype.catch(iterable)
            Promise.prototype.finally(iterable)
            Promise.race(iterable)
                方法返回一个 promise，一旦迭代器中的某个promise解决或拒绝，返回的 promise就会解决或拒绝。
            Promise.reject(reason)
            Promise.resolve(value)
            Promise.prototype.then(onFulfilled[, onRejected])
                onFulfilled 可选
                      当 Promise 变成接受状态（fulfilled）时调用的函数。
                      该函数有一个参数，即接受的最终结果（the fulfillment  value）。
                      如果该参数不是函数，则会在内部被替换为 (x) => x，即原样返回 promise 最终结果的函数
                onRejected 可选
                      当 Promise 变成拒绝状态（rejected）时调用的函数。
                      该函数有一个参数，即拒绝的原因（rejection reason）。  
                      如果该参数不是函数，则会在内部被替换为一个 "Thrower" 函数 
                      (it throws an error it received as argument)。
        Promise的链式调用
            用 promise.then()，promise.catch() 和 promise.finally() 
            这些方法将进一步的操作与一个变为已敲定状态的 promise 关联起来。
            这些方法还会返回一个新生成的 promise 对象。    
 *    4、手写promise:
 */
/**
 * 1、promise.all()
 */
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
    console.log(values);
});
// expected output: Array [3, 42, "foo"]

/**
 * 2、promise.any()
 */
const pErr = new Promise((resolve, reject) => {
    reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
    console.log(value);
    // pFast fulfils first
})
// 期望输出: "很快完成"
/**
 * 3.promise.finally() 方法返回一个Promise。
 * 在promise结束时，无论结果是fulfilled或者是rejected，都会执行指定的回调函数。
 * 这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
 * 这避免了同样的语句需要在then()和catch()中各写一次的情况。
 */
let isLoading = true;

fetch(myRequest).then(function (response) {
    var contentType = response.headers.get("content-type");
    if (contentType && contentType.includes("application/json")) {
        return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
})
    .then(function (json) { /* process your JSON further */ })
    .catch(function (error) { console.log(error); })
    .finally(function () { isLoading = false; });
/**
 * 4、promise.race(iterator)
 * 一旦迭代器中的某个promise解决或拒绝，返回的 promise就会解决或拒绝。
 */
const promise4 = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, 'one');
});

const promise5 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'two');
});

Promise.race([promise4, promise5]).then((value) => {
    console.log(value);
    // Both resolve, but promise2 is faster
});
// expected output: "two"